#ifndef TABLEWIDGETPAGESHELL_H
#define TABLEWIDGETPAGESHELL_H

#include <QObject>
#include "./TableWidgetShell.h"
#include "../Page/PageSelectionShell.h"

/**
 * @brief The TableWidgetPageShell class
 * TableWidgetShell + PageShell，具备翻页功能的Table
 *
 * FIXME：
 * 1 初始化时需要把完整的列表加载，导致当数据量大的时候，耗时较长，修改为 数据库+动态读取？回调读取？
 * 2 现在对每一列更新、设置值都是使用QVariant，后续可以考虑PaVarRef；
 *
 */
class TableWidgetPageShell : public QObject{
    Q_OBJECT
public:
    TableWidgetPageShell(QObject *parent = nullptr);
    virtual ~TableWidgetPageShell() {}


    // [-] shell
    /**
     * @brief shellTable 设置目标QTableWidget
     * @param tableWidget
     */
    void shellTable(QTableWidget *tableWidget);
    /**
     * @brief shellPage 设置翻页相关控件
     * @param first 首页
     * @param previous 上一页
     * @param page 当前页，固定格式x/x
     * @param next 下一页
     * @param last 最后一页
     * @param pageSwitch 页输入切换
     * @param availableCountPerPage 每页显示条目数切换
     * @param total 总的条目数量
     */
    void shellPage(QAbstractButton *first, QAbstractButton *previous, QLabel *page, QAbstractButton *next, QAbstractButton *last, QLineEdit *pageSwitch, QComboBox *availableCountPerPage, QLabel *total);
    // [!] shell


    // [-] config
    /**
     * @brief configColumn 配置列。（废弃）
     * @param titles 列标题。
     * @param keys 列关键字。
     * @param cls 列控件类型，暂不支持原生类型，自定义需要添加Q_INVOKABLE和继承CellBase，详细可以参考LabelCell。
     */
    void configColumn(const QStringList titles, const QStringList &keys, const QList<QMetaObject> &cls);
    TableWidgetShell& tableWidgetShell(){return _tableShell;}
    /**
     * @brief configColumnIndex 配置序号列的关键字，配置之后可以根据实际所在行和页显示序号。
     * @param key
     */
    void configColumnIndex(const QString &key);
    /**
     * @brief configRowRtCal 配置动态行数据调整，因为选中标记外部存储，某一些外部操作导致选中标记修改，并且在发生修改时，
     * 没有对shell选中值进行修改，所以当切换页时需要对行进行检查，合理的做法时一并修改shell的选中值，但是这可能需要对原有项目改动大，
     * 故这里设置一个切换页时，动态查询。
     * @param rtCal 动态查询的回调，有两个参数，rowData 和 rowSelected。
     * rowData会传入行数据，并有需要时，可以进行修改。
     * rowSelected会传入false，当需要选中该行时，可以将其设置为true。
     */
    void configRowRtCal(std::function<void(QVariantMap &rowData, bool &rowSelected)> rtCal);
    /**
     * @brief configCountPerPage 配置页可选择条目数。
     * @param count 默认显示的条目数，需要是可选择中已有值。
     * @param available 可以选择的条目数。
     */
    void configCountPerPage(int count, QList<int> available);
    // [!] config


    // [-] action
    /**
     * @brief appendData 追加行。
     * @param data
     */
    void appendData(const QVariantMap &data);
    /**
     * @brief insertDataAtRow 在当前页指定行插入新行。
     * @param row 指定的页行，注意：这是当前页的行号。
     * @param data 需要插入行数据。
     */
    void insertDataAtRow(int row, const QVariantMap &data);
    /**
     * @brief insertDataAtIndex 在指定行插入新行。
     * @param index 指定的页行，注意：这是包含所有页的行号。
     * @param data 需要插入行数据。
     */
    void insertDataAtIndex(int index, const QVariantMap &data);
    /**
     * @brief removeDataAtRow 删除当前页指定行。
     * @param row 参考 insertDataAtRow 中的参数 row 。
     */
    void removeDataAtRow(int row);
    /**
     * @brief removeDataAtIndex 删除指定行。
     * @param index 参考 insertDataAtIndex 中的参数 index 。
     */
    void removeDataAtIndex(int index);
    // [!] action

    // [-] action
    /**
     * @brief getDataAll 获取所有行数据。
     * @return
     */
    QVariantList getDataAll();
    /**
     * @brief getData 获取当前页行数据。
     * @return
     */
    QVariantList getData();
    QVariantMap getDataAtRow(int row);
    QVariantMap getDataAtIndex(int index);
    QVariantMap takeDataAtRow(int row);
    QVariantMap takeDataAtIndex(int index);
    // [!] action

    void setDataAll(const QVariantList &datas);
    void setDataAtRow(int row, const QVariantMap &data);
    void setDataAtIndex(int index, const QVariantMap &data);
    void updateDataAtRow(int row, const QVariantMap &data);
    void updateDataAtIndex(int index, const QVariantMap &data);
    void updateDataEqualTo(const QVariantMap equalTo, const QVariantMap &data);

    int findIndexEqualTo(const QVariantMap &data);
    void selectAtRow(int row);
    void selectAtIndex(int index);

    // signal
signals:
    void sigEvent(int row, QString name, QVariant info);

private:
    void setSelectIndex(int index);
    void updateTable();

private slots:
    void tableShell_onEvent(int row, QString name, QVariant info);
    void tableShell_onDataChanged(int row);
    void pageShell_onEvent(QString name, QVariant info);

private:
    QVariantList _data;
    TableWidgetShell _tableShell;
    PageSelectionShell _pageShell;

    QString _indexKey;
    std::function<void(QVariantMap &rowData, bool &rowSelected)> _rowRtCal;
};

#endif
